package com.sq.partner.manager.service.impl;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.springframework.stereotype.Service;

import com.sq.partner.manager.common.Config;
import com.sq.partner.manager.common.Constants;
import com.sq.partner.manager.common.Result;
import com.sq.partner.manager.dao.CardInfoDao;
import com.sq.partner.manager.dao.CommamtFeeDao;
import com.sq.partner.manager.dao.FacadePaymentDao;
import com.sq.partner.manager.dao.OutboundCardApplyDao;
import com.sq.partner.manager.mybatis.model.CardInfo;
import com.sq.partner.manager.mybatis.model.FacadeNewPayment;
import com.sq.partner.manager.mybatis.model.FacadePayment;
import com.sq.partner.manager.service.ExternalPaymentCardService;
import com.sq.partner.manager.sso.UMClient;
import com.sq.partner.manager.sso.webservice.UserInfo;
import com.sq.partner.manager.util.FreeMarkerUtil;
import com.sq.partner.manager.util.LogUtil;
import com.sq.partner.manager.util.StrUtil;
import com.sq.partner.manager.webservice.ReceiptAndPaymentClient;

/**
 * 对外收付系统实现类Service
 * 
 * @author zhouxiuxiu
 *
 */
@Service
public class ExternalPaymentCardServiceImpl implements
        ExternalPaymentCardService {
    private static Logger logger = LogUtil
            .getLog(ExternalPaymentCardServiceImpl.class);
    
    @Resource
    private CardInfoDao cardInfoDao;
    @Resource
    private FacadePaymentDao facadePayDao;
    @Resource
    private OutboundCardApplyDao outboundDao;
    @Resource
    private CommamtFeeDao commamtFeeDao;
    
    /**
     * 激活卡缴费传收付接口（2103）
     * @param facadePayment
     * @param employeeNo
     * @param userCode
     * @throws Exception
     */
    @Override
    public Result cardPayToPayment(FacadePayment facadePayment, 
            String employeeNo, String userCode) throws Exception{
        HashMap<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("commamtId", facadePayment.getPayId());
        if (StrUtil.isEmpty(employeeNo)) {
            UserInfo userInfo = null;
            try {
                userInfo = UMClient.getUser(userCode);
            } catch (Exception e) {
                return Result.error("UM系统取得数字工号失败，请联系管理员");
            }
            if (userInfo == null) {
                return Result.error("UM系统取得数字工号失败，请联系管理员");
            }
            employeeNo = userInfo.getEmployeeNo();
        }
        logger.info("支付ID:[" + facadePayment.getPayId() + "]传收付请求开始");
        long time1 = System.currentTimeMillis();
        //交易流水号
        String serialNumber = generateTradingSerialNumber();
        //取得缴费卡单list
        List<CardInfo> cardList = cardInfoDao.getCardInfoListByCommantId(
                facadePayment.getPayId());
        if (cardList == null || cardList.size() == 0) {
            return Result.error("出库ID："+facadePayment.getPayId()+"下没有卡单信息");
        }

        String paymentType = facadePayment.getPaymentType();
        String balType = paymentType;
        /*
         * 支付平台                 收付传值
            11  中国银联无卡支付            019
            1   中国银联网关支付            019
            12  上海银联（上海车险）      019
            13  非上海银联               019 
            7   微信                      016
            4   财付通（已停用）            报错
            5   支付宝                 017
            3   快钱支付                    018
            6   快钱支付WAP             018
            110 招商聚合                    110
            111 中信聚合-------111
            112 通联代扣-------112
         */
        if (Constants.WX_BIll99.equals(paymentType)
                || Constants.WX_BIll99WAP.equals(paymentType)) {
            balType = Constants.PAYMODE_TYPE_018;//快钱
        } else if (Constants.WX_ALIPAY.equals(paymentType)) {
            balType = Constants.PAYMODE_TYPE_017;//支付宝
        } else if (Constants.WX_WECHAT.equals(paymentType)) {
            balType = Constants.PAYMODE_TYPE_016;//微信
        } else if (Constants.WX_CHINAPAY.equals(paymentType)
                || Constants.WX_CHINANCPAY.equals(paymentType)
                || Constants.WX_SHYL.equals(paymentType)
                || Constants.WX_FSHYL.equals(paymentType)) {
            balType = Constants.PAYMODE_TYPE_019;//银联无卡支付
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("balType", balType);
        map.put("USER_NAME", Config.getProp(Constants.RECEIPT_WEBSERVICE_USER_NAME));
        map.put("USER_PSW", Config.getProp(Constants.RECEIPT_WEBSERVICE_USER_PSW));
        map.put("cardInfo", cardList.get(0));
        map.put("operatorNo", cardList.get(0).getOperatorNo() == null ? cardList.get(0)
                .getAgentNo() : cardList.get(0).getOperatorNo());
        map.put("facadePayment", facadePayment);
        map.put("SERIALNUMBER", serialNumber);
        map.put("TRANSRNO", Constants.GW_CH_TX_2103);
        map.put("employeeNo", employeeNo);
        String requestXml = FreeMarkerUtil.process(Config.getProp(
                Constants.PAY_2103_TEMPLATES), map);
        logger.info("激活卡缴费传收付请求报文：" + requestXml);
        String responseXml = "";
        try {
        	//出库表回传收付状态设置为回传收付处理中
            paramMap.put("backPayFlag", "1");
            commamtFeeDao.updateBackPayFlagByCommamtId(paramMap);
            responseXml = ReceiptAndPaymentClient.getRequest(requestXml);
        } catch (Exception e) {
            logger.info("激活卡缴费信息回传收付系统超时或失败");
            logger.info(e);
            paramMap.put("backPayFlag", "3");
            commamtFeeDao.updateBackPayFlagByCommamtId(paramMap);
            return Result.error("激活卡缴费信息回传收付系统超时或失败");
        }
        logger.info("激活卡缴费传收付系统完成执行时间:" + (System.currentTimeMillis() - time1));
        logger.info("激活卡缴费传收付系统返回报文：" + responseXml);
        Document document = DocumentHelper.parseText(responseXml);
        Element root = document.getRootElement();
        String resultCode = selectSingleNodeByRoot(root,
                "/INSUREQ/MAIN/RESULTCODE");
        String resultDesc = selectSingleNodeByRoot(root,
                "/INSUREQ/MAIN/ERR_INFO");
        if (StrUtil.isNotEmpty(resultDesc) && resultDesc.contains(
                "SQLCODE=-803")) {
            resultCode = "0000";
        }
        if (!"0000".equals(resultCode)) {
            logger.info("激活卡缴费信息回传收付系统失败:------------->" + resultDesc);
            paramMap.put("backPayFlag", "3");
            commamtFeeDao.updateBackPayFlagByCommamtId(paramMap);
            return Result.error(resultDesc);
        }
        paramMap.put("backPayFlag", "2");
        commamtFeeDao.updateBackPayFlagByCommamtId(paramMap);
        logger.info("支付ID:[" + facadePayment.getPayId() + "]传收付系统请求发送完成");
        return Result.success("激活卡缴费信息回传收付系统成功");
    }
    
    // 集中收款平台对接 2019/03/12 zhouxx start
    /**
     * 激活卡新支付方式传收付接口（2103）
     * @param facadeNewPayment
     * @param employeeNo
     * @param userCode
     * @throws Exception
     */
    @Override
    public Result cardNewPayToPayment(FacadeNewPayment facadeNewPayment, 
            String employeeNo, String userCode) throws Exception{
        HashMap<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("commamtId", facadeNewPayment.getPayId());
        if (StrUtil.isEmpty(employeeNo)) {
            UserInfo userInfo = null;
            try {
                userInfo = UMClient.getUser(userCode);
            } catch (Exception e) {
                return Result.error("UM系统取得数字工号失败，请联系管理员");
            }
            if (userInfo == null) {
                return Result.error("UM系统取得数字工号失败，请联系管理员");
            }
            employeeNo = userInfo.getEmployeeNo();
        }
        logger.info("支付ID:[" + facadeNewPayment.getPayId() + "]传收付请求开始");
        long time1 = System.currentTimeMillis();
        //交易流水号
        String serialNumber = generateTradingSerialNumber();
        //取得缴费卡单list
        List<CardInfo> cardList = cardInfoDao.getCardInfoListByCommantId(
                facadeNewPayment.getPayId());
        if (cardList == null || cardList.size() == 0) {
            return Result.error("出库ID："+facadeNewPayment.getPayId()+"下没有卡单信息");
        }

        String paymentType = facadeNewPayment.getPayType();
        String balType = paymentType;
        /*
         * 集中收款平台                       收付传值
            3   快钱支付                    018
            7   微信                           016
            13  银联                           019
            110 招商聚合                   110
            111 中信聚合-------111
         */
        if (Constants.NEWPAY_TYPE_3.equals(paymentType)) {
            balType = Constants.PAYMODE_TYPE_018;//快钱
        } else if (Constants.NEWPAY_TYPE_7.equals(paymentType)) {
            balType = Constants.PAYMODE_TYPE_016;//微信
        } else if (Constants.NEWPAY_TYPE_13.equals(paymentType)) {
            balType = Constants.PAYMODE_TYPE_019;//银联支付
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("balType", balType);
        map.put("USER_NAME", Config.getProp(Constants.RECEIPT_WEBSERVICE_USER_NAME));
        map.put("USER_PSW", Config.getProp(Constants.RECEIPT_WEBSERVICE_USER_PSW));
        map.put("cardInfo", cardList.get(0));
        map.put("operatorNo", cardList.get(0).getOperatorNo() == null ? cardList.get(0)
                .getAgentNo() : cardList.get(0).getOperatorNo());
        map.put("facadeNewPayment", facadeNewPayment);
        map.put("SERIALNUMBER", serialNumber);
        map.put("TRANSRNO", Constants.GW_CH_TX_2103);
        map.put("employeeNo", employeeNo);
        String requestXml = FreeMarkerUtil.process(Config.getProp(
                Constants.NEWPAY_2103_TEMPLATES), map);
        logger.info("激活卡缴费传收付请求报文：" + requestXml);
        String responseXml = "";
        try {
            //出库表回传收付状态设置为回传收付处理中
            paramMap.put("backPayFlag", "1");
            commamtFeeDao.updateBackPayFlagByCommamtId(paramMap);
            responseXml = ReceiptAndPaymentClient.getRequest(requestXml);
        } catch (Exception e) {
            logger.info("激活卡缴费信息回传收付系统超时或失败");
            logger.info(e);
            paramMap.put("backPayFlag", "3");
            commamtFeeDao.updateBackPayFlagByCommamtId(paramMap);
            return Result.error("激活卡缴费信息回传收付系统超时或失败");
        }
        logger.info("激活卡缴费传收付系统完成执行时间:" + (System.currentTimeMillis() - time1));
        logger.info("激活卡缴费传收付系统返回报文：" + responseXml);
        Document document = DocumentHelper.parseText(responseXml);
        Element root = document.getRootElement();
        String resultCode = selectSingleNodeByRoot(root,
                "/INSUREQ/MAIN/RESULTCODE");
        String resultDesc = selectSingleNodeByRoot(root,
                "/INSUREQ/MAIN/ERR_INFO");
//        if (StrUtil.isNotEmpty(resultDesc) && resultDesc.contains(
//                "SQLCODE=-803")) {
//            resultCode = "0000";
//        }
        if (!"0000".equals(resultCode)) {
            logger.info("激活卡缴费信息回传收付系统失败:------------->" + resultDesc);
            paramMap.put("backPayFlag", "3");
            commamtFeeDao.updateBackPayFlagByCommamtId(paramMap);
            return Result.error(resultDesc);
        }
        paramMap.put("backPayFlag", "2");
        commamtFeeDao.updateBackPayFlagByCommamtId(paramMap);
        logger.info("支付ID:[" + facadeNewPayment.getPayId() + "]传收付系统请求发送完成");
        return Result.success("激活卡缴费信息回传收付系统成功");
    }
    // 集中收款平台对接 2019/03/12 zhouxx end
    
    /**
     * 取得唯一交易流水号
     * @return
     * @throws Exception
     */
    private String generateTradingSerialNumber() throws Exception {
        StringBuffer s = new StringBuffer();
        synchronized ("zz") {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            s.append(calendar.get(Calendar.YEAR));
            int month = calendar.get(Calendar.MONTH) + 1;
            if (month < 10) {
                s.append("0" + month);
            } else {
                s.append(month);
            }
            int day = calendar.get(Calendar.DATE);
            if (day < 10) {
                s.append("0" + day);
            } else {
                s.append(day);
            }
            int hour = calendar.get(Calendar.HOUR_OF_DAY);
            if (hour < 10) {
                s.append("0" + hour);
            } else {
                s.append(hour);
            }
            int min = calendar.get(Calendar.MINUTE);
            if (min < 10) {
                s.append("0" + min);
            } else {
                s.append(min);
            }
            int sec = calendar.get(Calendar.SECOND);
            if (sec < 10) {
                s.append("0" + sec);
            } else {
                s.append(sec);
            }
            int num = (int)(Math.random()*100);
            if (num <10) {
                s.append("0" + num);
            } else {
                s.append(num);
            }
        }
        return "JHK" + s.toString();
    }
    
    /**
     * 取得返回报文节点值
     * @param root
     * @param path
     * @return
     */
    private String selectSingleNodeByRoot(Element root, String path) {
        Node node = root.selectSingleNode(path);
        if (node == null) {
            return "";
        } else {
            return node.getText();
        }
    }
}
